Skip to main content

Overview

The ProductoModel class provides simple read-only access to the product catalog stored in the producto database table. It supports listing all available products and retrieving individual product details by item code. Database Table: producto Key Responsibilities:
  • List all products for selection interfaces
  • Retrieve product details by item code
  • Provide product information for return registration
This model only implements read operations. Product catalog management (create, update, delete) is handled through separate administrative interfaces not included in the DevolutionSync core.

Constructor

public function __construct()
Initializes the model and establishes database connection using Conexion::Conectar().

Methods

listarTodos()

public function listarTodos()
Retrieves all products from the catalog, ordered alphabetically by description. Used to populate product selection dropdowns and autocomplete interfaces when auxiliary users register returns. Returns: array - Array of associative arrays with the following structure:
item
string
Product item code (unique identifier)
descripcion
string
Product description or name
SELECT item, descripcion 
FROM producto 
ORDER BY descripcion ASC

obtenerPorItem()

public function obtenerPorItem($item)
Retrieves detailed information for a specific product by its item code. Used to auto-fill product description when an auxiliary user enters or selects an item code during return registration.
item
string
required
The product item code to search for (e.g., “PROD001”)
Returns: array|false - Associative array with product data, or false if not found
item
string
Product item code (matches the search parameter)
descripcion
string
Product description or name
SELECT item, descripcion 
FROM producto 
WHERE item = ?
This method returns false (not null) when no product is found. Always use explicit boolean checks (if ($producto) or if ($producto !== false)) to handle missing products correctly.

Database Schema

Table: producto The producto table contains the complete product catalog with inventory control fields:
ColumnTypeDescriptionUsed by Model
idINT (PK, AUTO_INCREMENT)Primary keyNo
itemVARCHAR (UNIQUE)Product item codeYes
descripcionVARCHARProduct name/descriptionYes
minimoDECIMALMinimum inventory levelNo
maximoDECIMALMaximum inventory levelNo
pesoPromDECIMALAverage weight per unitNo
The ProductoModel class intentionally excludes minimo, maximo, and pesoProm fields because:
  1. Return registration doesn’t require inventory data - Auxiliary users only need to identify the product (item + descripcion)
  2. Separation of concerns - Inventory management is handled by separate warehouse systems
  3. Simplified API - Reduces payload size and complexity for frontend interfaces
  4. Data privacy - Internal inventory targets are not exposed to all auxiliary users
If your implementation requires weight calculations (e.g., auto-calculating cantidad_kg from pesoProm × cantidad_und), you can extend the model:
public function obtenerConPeso($item) {
    $stmt = $this->db->prepare("SELECT item, descripcion, pesoProm FROM producto WHERE item = ?");
    $stmt->execute([$item]);
    return $stmt->fetch();
}

Integration with DevolucionModel

The ProductoModel is typically used in conjunction with DevolucionModel during the return registration workflow:
// Step 1: Load product catalog for selection
$productoModel = new ProductoModel();
$productos = $productoModel->listarTodos();

// User selects a product by item code
$itemSeleccionado = 'PROD001';

// Step 2: Retrieve product details
$producto = $productoModel->obtenerPorItem($itemSeleccionado);

if (!$producto) {
    die('Producto no encontrado');
}

// Step 3: Use product data in return registration
$devolucionModel = new DevolucionModel();
$datos = [
    'item_producto' => $producto['item'],
    'descripcion_producto' => $producto['descripcion'],
    // ... other return data
];

$devolucionModel->guardar($datos);

Frontend Integration Examples

Select Dropdown with All Products

<select id="producto" name="item_producto" required>
    <option value="">-- Seleccione un producto --</option>
    <?php
    $model = new ProductoModel();
    $productos = $model->listarTodos();
    foreach ($productos as $p) {
        echo "<option value='{$p['item']}'>{$p['descripcion']}</option>";
    }
    ?>
</select>

AJAX Autocomplete

// Frontend JavaScript
const itemInput = document.getElementById('item_producto');
const descripcionInput = document.getElementById('descripcion_producto');

itemInput.addEventListener('blur', async function() {
    const item = this.value.trim();
    if (!item) return;
    
    const response = await fetch(`/api/productos.php?item=${item}`);
    const data = await response.json();
    
    if (data.success) {
        descripcionInput.value = data.producto.descripcion;
    } else {
        alert('Producto no encontrado');
        this.value = '';
    }
});
// Backend API: api/productos.php
require_once '../Models/ProductoModel.php';

$item = $_GET['item'] ?? '';
$model = new ProductoModel();
$producto = $model->obtenerPorItem($item);

header('Content-Type: application/json');
if ($producto) {
    echo json_encode(['success' => true, 'producto' => $producto]);
} else {
    echo json_encode(['success' => false, 'mensaje' => 'Producto no encontrado']);
}

Performance Considerations

Caching Recommendation: Since product catalogs are relatively static, consider implementing caching for listarTodos() results:
public function listarTodos() {
    // Check cache first
    $cacheKey = 'productos_todos';
    $cached = apcu_fetch($cacheKey);
    if ($cached !== false) {
        return $cached;
    }
    
    // Fetch from database
    $stmt = $this->db->prepare("SELECT item, descripcion FROM producto ORDER BY descripcion ASC");
    $stmt->execute();
    $result = $stmt->fetchAll();
    
    // Store in cache for 1 hour
    apcu_store($cacheKey, $result, 3600);
    return $result;
}
This reduces database load when multiple users register returns simultaneously.